# HTU21D(F)/Si7013/Si7020/Si7021/SHT21 i2c based temperature sensors support
#
# Copyright (C) 2020  Lucio Tarantino <lucio.tarantino@gmail.com>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import logging
import threading
import time

from sensor.HTU21D import HTU21D

HTU21D_I2C_ADDR = 0x40


class HTU21D_HOST:
    def __init__(self, config):
        self.printer = config.get_printer()
        self.name = config.get_name().split()[-1]
        self.reactor = self.printer.get_reactor()
        self.report_time = config.getint('htu21d_report_time', 30, minval=5)
        self.i2c_addr = config.getint('i2c_address', HTU21D_I2C_ADDR)
        self.temp = self.min_temp = self.max_temp = self.humidity = 0.
        # self.sample_timer = self.reactor.register_timer(self._sample_htu21d)
        self.printer.add_object("htu21d_host " + self.name, self)
        self.printer.register_event_handler("klippy:connect",
                                            self.handle_connect)
        self.printer.register_event_handler("klippy:disconnect",
                                            self.handle_disconnect)
        self.htu21d_thread = None

    def handle_connect(self):
        self.htu21d_thread = HTU21DThread(self)
        self.htu21d_thread.start()

    def handle_disconnect(self):
        if self.htu21d_thread is not None:
            self.htu21d_thread._stop()

    def setup_minmax(self, min_temp, max_temp):
        self.min_temp = min_temp
        self.max_temp = max_temp

    def setup_callback(self, cb):
        self._callback = cb

    def get_report_time_delta(self):
        return self.report_time

    def get_temp(self, eventtime):
        return self.temp, 0.

    def get_status(self, eventtime):
        return {
            'temperature': round(self.temp, 2),
            'humidity': round(self.humidity, 2)
        }

    def update(self, temp, humidity):
        if temp is not None:
            self.temp = temp
        if humidity is not None:
            self.humidity = humidity

        mcu = self.printer.lookup_object('mcu')
        measured_time = self.reactor.monotonic()
        logging.info("htu21d_host temp=%s, humidity=%s" % (self.temp, self.humidity))
        self._callback(mcu.estimated_print_time(measured_time), self.temp)


class HTU21DThread(threading.Thread):
    def __init__(self, obj):
        super(HTU21DThread, self).__init__()
        self.obj = obj
        self._stop = False

    def get_HTU21D(self):
        return HTU21D(1, self.obj.i2c_addr)

    def stop(self):
        logging.info("htu21d_host stop")
        self._stop = True
        self.join(self.obj.report_time)

    def start(self):
        logging.info("htu21d_host start")
        self._stop = False
        super(HTU21DThread, self).start()

    def run(self):
        while not self._stop:
            try:
                htu21d = self.get_HTU21D()
                h = htu21d.humidity()
                t = htu21d.temperature()
                self.obj.update(t.C, h.RH)
            except Exception as e:
                logging.exception(e)
            time.sleep(self.obj.report_time)


def load_config(config):
    # Register sensor
    pheater = config.get_printer().lookup_object("heaters")
    pheater.add_sensor_factory('HTU21D_HOST', HTU21D_HOST)
